package com.alipay.rebate.shop.utils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.*;

import com.github.pagehelper.PageInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ReflectsUtils {

  private static  Logger logger = LoggerFactory.getLogger(ReflectsUtils.class);

  public  static boolean compareObject(Object o1,Object o2){

    Boolean result = true;

    if (o1 == null && o2 == null){
      return true;
    }

    if (o1 != null && o2 == null || o1 == null && o2 != null){
      return false;
    }

    // 若传过来的对象为基本数据类型
    if ((o1 instanceof Integer && o2 instanceof Integer) ||
            (o1 instanceof Long && o2 instanceof Long) ||
            (o1 instanceof Boolean && o2 instanceof Boolean) ||
            (o1 instanceof BigDecimal && o2 instanceof BigDecimal) ||
            (o1 instanceof Map && o2 instanceof Map)){
      logger.debug("basic type compare");

      if (compareValue(o1, o2)){
        return true;
      }

    }

    if (o1 instanceof List && o2 instanceof  List){
      if (((List) o1).size() != ((List) o2).size()){
        return false;
      }

      if (((List) o1).containsAll((List) o2)){
        return true;
      }

    }


    if (o1.getClass().isInstance(o2)){
      try {
        //获取类对象
        Class<?> aClass = Class.forName(o1.getClass().getName());
        Field[] fields = aClass.getDeclaredFields();

        for (Field temp : fields){
          String fieldName = temp.getName();
          logger.debug("fieldName is : {}",fieldName);

          // 跳过用户对象lastLoginIp 的判断
          if(fieldName.equals("lastLoginIp") || fieldName.equals("userRegisterIp")){
            continue;
          }

          // 组装属性对应的get方法
          String methodName = "get" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);

          //通过get方法获取属性名
          Object invoke1 = aClass.getMethod(methodName).invoke(o1);
          Object invoke2 = aClass.getMethod(methodName).invoke(o2);

          logger.debug("invoke1 and invoke2 is : {}, {}",invoke1,invoke2);
          if(invoke1 == null && invoke2 == null){
            continue;
          }

          // 日期类型不校验
          if(invoke1 instanceof Date){
            continue;
          }

          // 基本类型比较
          if (invoke1 instanceof Integer || invoke1 instanceof String || invoke1 instanceof Short
              || invoke1 instanceof Byte || invoke1 instanceof Long || invoke1 instanceof Character
              ||  invoke1 instanceof Float || invoke1 instanceof Double || invoke1 instanceof Boolean
              || invoke1 instanceof BigDecimal || invoke1 instanceof Map){
            logger.debug("basic type compare");
            if (!compareValue(invoke1,invoke2)){
              result = false;
              break;
            }

          }else if (invoke1 instanceof List){
            logger.debug("basic type compare");
            // TODO (需要添加list比较代码)
            //判断吧list是否为空

            if (invoke1 == null && invoke2 == null){
              continue;
            }
            if (((List) invoke1).size() != ((List) invoke2).size()){
              result = false;
              break;
            }

            for(int i = 0 ; i < ((List) invoke1).size() ; i++ ){
              if (!compareObject(((List) invoke1).get(i),((List) invoke2).get(i))){
                result = false;
                break;
              }
            }

            if (!result){
              break;
            }


          }else{
            // 对象比较
            if (!compareObject(invoke1, invoke2)){
              result = false;
              break;
            }
          }

        }

      }catch(ClassNotFoundException e){
        return false;
      }catch(NoSuchMethodException e){
        return false;
      }catch (InvocationTargetException e){
        return false;

      }catch (IllegalAccessException e){
        return false;

      }
    }else{
      return false;
    }

    return result;
  }

  private static boolean compareValue(Object o1,Object o2){
    logger.debug("o1 and o2 is : {}, {}",o1,o2);
    if (o1 == null || o2 == null){
      return false;
    }
    if (o1.equals(o2)){
      return true;
    }
    return false;
  }
}
